//
// Created by xiaoma on 2/2/21.
//

#include "Map.h"

template<typename K, typename V>
MapEntry<K, V>::MapEntry(const MapEntry<K, V> &mapEntry) {
    k = mapEntry.k;
    v = mapEntry.v;
}

template<typename K, typename V>
Map<K, V>::Map(int n) {
    _len = n;
    _size = 0;
    _entries = new MapEntry<K, V>[n];
}

template<typename K, typename V>
void Map<K, V>::put(K k, V v) {
    for (int i = 0; i < _size; i++) {
        if (_entries[i].k->equal(k) == Universe::True) {
            _entries[i].v = v;
            return;
        }
    }
    expand();
    _entries[_size++] = MapEntry<K, V>(k, v);
}

template<typename K, typename V>
bool Map<K, V>::hasKey(K k) {
    return getIndex(k) >= 0;
}

template<typename K, typename V>
V Map<K, V>::getValue(K k) const {
    int index = getIndex(k);
    if (index >= 0) {
        return _entries[index].v;
    } else {

        return Universe::None;
    }
}

template<typename K, typename V>
V Map<K, V>::remove(K k) {
    int index = getIndex(k);
    if (index < 0) {
        return Universe::None;
    }
    auto v = _entries[index].v;
    _entries[index] = _entries[--_size];
    return v;
}

template<typename K, typename V>
int Map<K, V>::getIndex(K k) const {
    for (int i = 0; i < _size; i++) {
        if (_entries[i].k->equal(k) == Universe::True) {
            return i;
        }
    }
    return -1;
}

template<typename K, typename V>
void Map<K, V>::expand() {
    if (_size < _len) {
        return;
    }
    auto tmp = _entries;
    _entries = new MapEntry<K, V>[_len << 1];
    for (int i = 0; i < _len; i++) {
        _entries[i].k = tmp[i].k;
        _entries[i].v = tmp[i].v;
    }
    _len <<= 1;
    delete[] tmp;
}

template
class Map<HiObject *, HiObject *>;